package cn.sccl.dirms.topo.discovery.task;

import cn.sccl.common.util.DateUtil;
import cn.sccl.common.util.StrUtils;
import cn.sccl.dirms.topo.discovery.Discovery;
import cn.sccl.dirms.topo.discovery.DiscoveryAPI;
import cn.sccl.dirms.topo.discovery.model.*;
import cn.sccl.dirms.topo.discovery.service.DiscoverTaskLogManager;
import cn.sccl.dirms.topo.discovery.service.DiscoveryDeviceManager;
import cn.sccl.dirms.topo.discovery.util.ComUtil;
import cn.sccl.dirms.topo.model.DiscoveryResult;
import cn.sccl.dirms.topo.service.DiscoveryResultManager;
import cn.sccl.common.zabbix.Zabbix;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
 * 执行自动扫描任务
 * 此任务为阻塞任务调度(一个任务执行完之后才能调度执行下一个任务--quartz)
 * 所用Job类 为StatefulJob.class类
 * <p/>
 * Created by julei on 2017/9/25.
 */
@Service("discoveryService")
public class DiscoveryService {

//    @Autowired
    private DiscoveryDeviceManager discoveryDeviceManager;

    @Autowired
    private DiscoverTaskLogManager logManager;

    @Autowired
    private DiscoveryResultManager discoveryResultManager;

    private DiscoverTask task;


    private static String LOG_TYPE_INFO = "info";
    private static String LOG_TYPE_ERRO = "error";
    private static String LOG_TYPE_WARN = "warn";


    /**
     * 将异常抛出，上级处理
     *
     * @param task
     * @param fireLogId
     * @throws InterruptedException
     */
    public void callTask(DiscoverTask task, final String fireLogId) throws InterruptedException {

        this.createCopy(task);//创建变量副本
        log(fireLogId, LOG_TYPE_INFO, "发现开始。");
        String ruleJsonStr = task.getDiscoverRuleDetail();
        Map ruleMap = JSONObject.parseObject(ruleJsonStr);


        DiscoveryResult discoveryResult = new DiscoveryResult();
        discoveryResult.setLogId(fireLogId);
        discoveryResult.setRuleDetail(ruleJsonStr);

        NetScan config = new NetScan(ruleMap);
        Discovery impl = new Discovery();
        List<String> ips = ComUtil.getIPSByRangeList(config.getIpRangeList());
        log(fireLogId, LOG_TYPE_INFO, "开始初次扫描Ip地址：" + ips.toString());

        DiscoveryConfig discoveryConfig = new DiscoveryConfig();
        List<DeviceInfo> firstDeviceList = impl.discoveryDevicesByIps(1000, ips, config.getSnmpConfigList(), discoveryConfig);
        impl.getDevList().addAll(firstDeviceList);
        log(fireLogId, LOG_TYPE_INFO, "初次扫描完成，发现设备【" + firstDeviceList.size() + "】台。");
        if (firstDeviceList.size() == 0) {
            log(fireLogId, LOG_TYPE_INFO, "未发现设备，请检查规则配置和网络情况。");
            return;
        }

        //转发表再发现
        log(fireLogId, LOG_TYPE_INFO, "开始深度探测。");
        impl.discoveryChildren(firstDeviceList, config.getSnmpConfigList(), discoveryConfig);
        List<DeviceInfo> deviceList = impl.getDevList();
        log(fireLogId, LOG_TYPE_INFO, "深度探测完成，共发现设备【" + deviceList.size() + "】台。");

        Zabbix zabbix = Zabbix.getZabbix();
        List<Map> elementList = new ArrayList<Map>();

        Map linkMap;
        List<Map> elementLinkList = new ArrayList<Map>();
        JSONObject result;
        Map<String, Object> mapResult, params, e;
        Map elementAndHost = new HashMap();
        Map<String, Object> resMap = new HashMap();
        Map<String, DeviceInfo> deviceMap = new HashMap();
        //去重
        ComUtil.removeDuplicate(deviceList);

        discoveryResult.setDeviceList(StrUtils.objectToBytes(deviceList));

        ConcurrentMap<String,Object> currentMap = new ConcurrentHashMap<String,Object>();
        currentMap.put("graphId",this.task.getGraphyId()) ;

        //保存发现记录
        for (DeviceInfo device : deviceList) {
            e = new HashMap<String, Object>();
            String ip = device.getDeviceIP();
            log(fireLogId, LOG_TYPE_INFO, "开始将设备写入系统：写入【" + device.getDeviceName() + "(" + ip + ")】");
            System.out.println("1:" + DateUtil.getLogNow());

//            NewHostResult newHostResult = discoveryDeviceManager.newHost(device,currentMap);
//
//            resMap.putAll(newHostResult.getNeElementMap());
//            resMap.putAll(newHostResult.getNeportMap());
//
//            String uuid = StrUtils.generateShortUuid();
//            elementAndHost.put(ip, uuid);
//            deviceMap.put(ip, device);
//            e.put("selementid", uuid);
//            e.put("elementid", newHostResult.getZabbixHostId());
//            e.put("elementtype", "0");
//            e.put("iconid_off", "128");
//            e.put("label", ip);
//            elementList.add(e);
        }
        log(fireLogId, LOG_TYPE_INFO, "开始发现设备链路关系。");
        List<LinkInfo> linkList = DiscoveryAPI.linkDeiscovery(deviceList, config.getDiscoveryConfig());
        discoveryResult.setLinkList(StrUtils.objectToBytes(linkList));
        log(fireLogId, LOG_TYPE_INFO, "开始发现设备链路关系完成，共发现【" + linkList.size() + "】条数据链路");
        if (linkList != null) {
            for (LinkInfo link : linkList) {
                String startIp = link.startDevice.getDeviceIP();
                String endIp = link.endDevice.getDeviceIP();
                //链路已存在，不再链接
                for (Map exists : elementLinkList) {
                    if (exists.get("selementid1").equals(elementAndHost.get(startIp)) && exists.get("selementid2").equals(elementAndHost.get(endIp))) {
                        continue;
                    }
                    if (exists.get("selementid2").equals(elementAndHost.get(startIp)) && exists.get("selementid1").equals(elementAndHost.get(endIp))) {
                        continue;
                    }
                }
                linkMap = new HashMap();

                linkMap.put("selementid1", elementAndHost.get(startIp));
                linkMap.put("selementid2", elementAndHost.get(endIp));
                log(fireLogId, LOG_TYPE_INFO, "开始将设备写入系统：写入【" + startIp + "---" + endIp + "】");
                System.out.println("2:" + DateUtil.getLogNow());
//                discoveryDeviceManager.newLink(link, resMap,currentMap);
                //资源拓扑图--连线
                elementLinkList.add(linkMap);
            }
        }

        log(fireLogId, LOG_TYPE_INFO, "开始同步拓扑图。");
        params = new HashMap();
        params.put("name", config.getMapName());
        params.put("width", 600);
        params.put("height", 600);
        params.put("links", elementLinkList);
        params.put("selements", elementList);
        result = zabbix.call("map.create", params);
        mapResult = (Map<String, Object>) result.get("result");
        if (mapResult != null) {
            List sysmapids = (List) mapResult.get("sysmapids");
            if (sysmapids.size() == 1) {
                String sysmapid = (String) sysmapids.get(0);
            }
        } else {
            System.out.println(result.toJSONString());
        }
        discoveryResultManager.save(discoveryResult);
        log(fireLogId, LOG_TYPE_INFO, "拓扑图发现完成。");

    }

    private void createCopy(DiscoverTask task) {
        this.task = task;
    }

    /**
     * 日志记录
     *
     * @param msg
     */
    private void log(String fireLogId, String type, String msg) {
        DiscoverTaskLog log = new DiscoverTaskLog();
        log.setTaskId(task.getId());
        log.setType(type);
        log.setTaskFireLogId(fireLogId);
        log.setMessage(DateUtil.getLogNow() + "：" + msg);
        logManager.save(log);
    }


}
